home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 February: Tool Chest / Dev.CD Feb 94.toast / Tool Chest / Development Platforms / AppsToGo / AppsToGo.src / DTS.Draw / TPieObj.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-18  |  13.9 KB  |  519 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        TPieObj.c
  5. ** Written by:    Eric Soldan
  6. **
  7. ** Copyright © 1992-1993 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11. /* You may incorporate this sample code into your applications without
  12. ** restriction, though the sample code has been provided "AS IS" and the
  13. ** responsibility for its operation is 100% yours.  However, what you are
  14. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  15. ** after having made changes. If you're going to re-distribute the source,
  16. ** we require that you make it clear in the source that the code was
  17. ** descended from Apple Sample Code, but that you've made changes. */
  18.  
  19. /* See the files "=How to write your app" and "=Using TreeObj.c" for information
  20. ** on this function. */
  21.  
  22. /* This file implements the messages for the pie object.  Many of the messages
  23. ** can be handled by the rect object, as they deal with a rect structure.  Only
  24. ** a few of them are pie-specific. */
  25.  
  26. /* We have a custom hit-test handler here because there are additional sizing
  27. ** grabbers for the pie object.  The other objects just have grabbers at the
  28. ** corners.  A pie object also has grabber objects to adjust the "pie-slice". */
  29.  
  30.  
  31.  
  32. /*****************************************************************************/
  33.  
  34.  
  35.  
  36. #include "App.h"            /* Get the application includes/typedefs, etc.    */
  37. #include "App.protos.h"        /* Get the prototypes for the application.        */
  38.  
  39. #ifndef __OSEVENTS__
  40. #include <OSEvents.h>
  41. #endif
  42.  
  43. #ifndef __OSUTILS__
  44. #include <OSUtils.h>
  45. #endif
  46.  
  47. #ifndef __QUICKDRAW__
  48. #include <Quickdraw.h>
  49. #endif
  50.  
  51. #ifndef __STRING__
  52. #include <String.h>
  53. #endif
  54.  
  55. #ifndef __TREEOBJ2__
  56. #include "TreeObj2.h"
  57. #endif
  58.  
  59. #ifndef __UTILITIES__
  60. #include "Utilities.h"
  61. #endif
  62.  
  63.  
  64.  
  65. static OSErr    PieLayerProc(LayerObj theLayer, short message);
  66.  
  67.  
  68.  
  69. /*****************************************************************************/
  70.  
  71.  
  72.  
  73. #pragma segment DrawObjects
  74. long    TPieObj(TreeObjHndl hndl, short message, long data)
  75. {
  76.     ClickInfo    *click;
  77.     Rect        rct;
  78.     TreeObjHndl    hhndl;
  79.     RgnHandle    rgn, oldClip, newClip;
  80.     short        arcs, arcl, arcs2, arcl2, diff, i, angle, h, w;
  81.     Point        pt, where, curMouse;
  82.     long        flip, newSize;
  83.     LayerObj    pieLayer;
  84.     EventRecord    option;
  85.     RGBColor    rgb, rgb2;
  86. #if VH_VERSION
  87.     char        *cptr;
  88. #endif
  89.  
  90.     switch (message) {
  91.         case INITMESSAGE:
  92.             TRectObj(hndl, message, data);
  93.             mDerefPie(hndl)->arcStart  = 0;
  94.             mDerefPie(hndl)->arcLength = 360;
  95.             break;
  96.  
  97.         case FREEMESSAGE:
  98.         case COPYMESSAGE:
  99.         case UNDOMESSAGE:
  100.         case CONVERTMESSAGE:
  101.         case FREADMESSAGE:
  102.         case FWRITEMESSAGE:
  103.         case HREADMESSAGE:
  104.         case HWRITEMESSAGE:
  105.         case GETOBJRECTMESSAGE:
  106.         case SECTOBJRECTMESSAGE:
  107.         case KEYMESSAGE:
  108.         case SETSELECTMESSAGE:
  109.         case GETSELECTMESSAGE:
  110.         case COMPAREMESSAGE:
  111.             return(TRectObj(hndl, message, data));
  112.             break;
  113.  
  114.         case GETBBOXMESSAGE:
  115.             return(TLineObj(hndl, message, data));
  116.             break;
  117.  
  118.         case HITTESTMESSAGE:
  119.             click = (ClickInfo *)data;
  120.             hhndl = (TreeObjHndl)TRectObj(hndl, message, data);
  121.                 /* We must call TRectObj::HITTESTMESSAGE to set some static
  122.                 ** variables that TRectObj::SELECTOBJMESSAGE uses. */
  123.             if ((!hhndl) && (click->message == HITTESTGRABBER)) {
  124.                 if (mDerefRoot(GetRootHndl(hndl))->numSelected == 1) {
  125.                     if (mDerefPie(hndl)->selected) {
  126.                         rct   = mDerefPie(hndl)->arc;
  127.                         where = click->localEvent.where;
  128.                         InsetRect(&rct, -4, -4);
  129.                         if (PtInRect(where, &rct)) {
  130.                             GetMouse(&curMouse);
  131.                             for (i = 0; i < 2; ++i) {
  132.                                 pt = (i) ? mDerefPie(hndl)->arcEnd : mDerefPie(hndl)->arcBegin;
  133.                                 rct.bottom = (rct.top  = pt.v - 3) + 6;
  134.                                 rct.right  = (rct.left = pt.h - 3) + 6;
  135.                                 if (PtInRect(where, &rct)) {
  136.                                     click->localEvent.where = pt;
  137.                                     click->offset.h         = pt.h - curMouse.h;
  138.                                     click->offset.v         = pt.v - curMouse.v;
  139.                                     click->oldFlip          = 0;
  140.                                     click->newFlip          = 0;
  141.                                     click->grabber          = 5 + i;
  142.                                     hhndl = hndl;
  143.                                     break;
  144.                                 }
  145.                             }
  146.                         }
  147.                     }
  148.                 }
  149.             }
  150.             return((long)hhndl);
  151.             break;
  152.  
  153.         case GETRGNMESSAGE:
  154.             rgn = NewRgn();
  155.             NewLayer(&pieLayer, nil, PieLayerProc, nil, 0, (long)hndl);
  156.             if (pieLayer) {
  157.                 SetLayerWorld(pieLayer);
  158.                 TPieObj(hndl, DRAWMESSAGE, DRAWMASK);
  159.                 BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  160.                 ResetLayerWorld(pieLayer);
  161.                 DisposeLayer(pieLayer);
  162.             }
  163.             return((long)rgn);
  164.             break;
  165.  
  166.         case SETOBJRECTMESSAGE:
  167.             TRectObj(hndl, message, data);
  168.             CalcPiePoints(hndl);
  169.             break;
  170.  
  171.         case DRAWMESSAGE:
  172.             rct = mDerefPie(hndl)->arc;
  173.             h   = mDerefCommon(hndl)->penHeight;
  174.             w   = mDerefCommon(hndl)->penWidth;
  175.             PenSize(w, h);
  176.             if (!EmptyRect(&rct)) {
  177.                 arcs = mDerefPie(hndl)->arcStart;
  178.                 arcl = mDerefPie(hndl)->arcLength;
  179.                 switch (data) {
  180.                     case DRAWOBJ:
  181.                         GetClip(oldClip = NewRgn());
  182.                         if (newClip = (RgnHandle)TOvalObj(hndl, GETRGNMESSAGE, 0))
  183.                             SetClip(newClip);
  184.                         if (gQDVersion)
  185.                             GetForeColor(&rgb);
  186.                         ForeColor(whiteColor);
  187.                         if (gQDVersion) {
  188.                             rgb2 = mDerefLine(hndl)->contentColor;
  189.                             RGBForeColor(&rgb2);
  190.                         }
  191.                         PaintArc(&rct, arcs, arcl);
  192.                         ForeColor(blackColor);
  193.                         if (gQDVersion) {
  194.                             rgb2 = mDerefLine(hndl)->borderColor;
  195.                             RGBForeColor(&rgb2);
  196.                         }
  197.                         FrameArc(&rct, arcs, arcl);
  198.                         pt = mDerefPie(hndl)->arcBegin;
  199.                         MoveTo(pt.h - (w / 2), pt.v - (w / 2));
  200.                         pt = mDerefPie(hndl)->center;
  201.                         LineTo(pt.h - (w / 2), pt.v - (w / 2));
  202.                         pt = mDerefPie(hndl)->arcEnd;
  203.                         LineTo(pt.h - (w / 2), pt.v - (w / 2));
  204.                         if (gQDVersion)
  205.                             RGBForeColor(&rgb);
  206.                         SetClip(oldClip);
  207.                         DisposeRgn(oldClip);
  208.                         if (newClip)
  209.                             DisposeRgn(newClip);
  210.                         break;
  211.                     case ERASEOBJ:
  212.                         EraseArc(&rct, arcs, arcl);
  213.                         break;
  214.                     case DRAWSELECT:
  215.                         if (mDerefPie(hndl)->selected) {
  216.                             TRectObj(hndl, message, data);
  217.                             for (i = 0; i < 2; ++i) {
  218.                                 pt = (i) ? mDerefPie(hndl)->arcEnd : mDerefPie(hndl)->arcBegin;
  219.                                 rct.bottom = (rct.top  = pt.v - 3) + 6;
  220.                                 rct.right  = (rct.left = pt.h - 3) + 6;
  221.                                 InvertRect(&rct);
  222.                                 arcl = mDerefPie(hndl)->arcLength;
  223.                                 if ((arcl == -360) || (!arcl) || (arcl == 360)) break;
  224.                             }
  225.                         }
  226.                         break;
  227.                     case DRAWGHOST:
  228.                         PenMode(patXor);
  229.                         FrameArc(&rct, arcs, arcl);
  230.                         break;
  231.                     case DRAWMASK:
  232.                         FillArc(&rct, arcs, arcl, (ConstPatternParam)&qd.black);
  233.                         FrameArc(&rct, arcs, arcl);
  234.                         pt = mDerefPie(hndl)->arcBegin;
  235.                         MoveTo(pt.h - (w / 2), pt.v - (w / 2));
  236.                         pt = mDerefPie(hndl)->center;
  237.                         LineTo(pt.h - (w / 2), pt.v - (w / 2));
  238.                         pt = mDerefPie(hndl)->arcEnd;
  239.                         LineTo(pt.h - (w / 2), pt.v - (w / 2));
  240.                         break;
  241.                 }
  242.             }
  243.             PenNormal();
  244.             break;
  245.  
  246.         case PRINTMESSAGE:
  247.             TPieObj(hndl, DRAWMESSAGE, DRAWOBJ);
  248.             break;
  249.  
  250. #if VH_VERSION
  251.         case VHMESSAGE:
  252.             cptr = ((VHFormatDataPtr)data)->data;
  253.             ccatchr(cptr, 13, 2);
  254.             ccat   (cptr, "$10: TPieObj:");
  255.             ccatchr(cptr, 13, 1);
  256.             ccat   (cptr, "  $00: selected = ");
  257.             ccatdec(cptr, mDerefPie(hndl)->selected);
  258.             ccatchr(cptr, 13, 1);
  259.             rct = mDerefPie(hndl)->arc;
  260.             ccat   (cptr, "  $02: pie      = (");
  261.             ccatdec(cptr, rct.top);
  262.             ccat   (cptr, ",");
  263.             ccatdec(cptr, rct.left);
  264.             ccat   (cptr, ",");
  265.             ccatdec(cptr, rct.bottom);
  266.             ccat   (cptr, ",");
  267.             ccatdec(cptr, rct.right);
  268.             ccat   (cptr, ")");
  269.             ccatchr(cptr, 13, 1);
  270.             ccat   (cptr, "  $0A: arcStart  = ");
  271.             ccatdec(cptr, mDerefPie(hndl)->arcStart);
  272.             ccatchr(cptr, 13, 1);
  273.             ccat   (cptr, "  $0C: arcLength = ");
  274.             ccatdec(cptr, mDerefPie(hndl)->arcLength);
  275.             ccatchr(cptr, 13, 1);
  276.             ccat   (cptr, "  $0E: center    = (");
  277.             ccatdec(cptr, mDerefPie(hndl)->center.v);
  278.             ccat   (cptr, ",");
  279.             ccatdec(cptr, mDerefPie(hndl)->center.h);
  280.             ccat   (cptr, ")");
  281.             ccatchr(cptr, 13, 1);
  282.             ccat   (cptr, "  $12: arcBegin  = (");
  283.             ccatdec(cptr, mDerefPie(hndl)->arcBegin.v);
  284.             ccat   (cptr, ",");
  285.             ccatdec(cptr, mDerefPie(hndl)->arcBegin.h);
  286.             ccat   (cptr, ")");
  287.             ccatchr(cptr, 13, 1);
  288.             ccat   (cptr, "  $16: arcEnd    = (");
  289.             ccatdec(cptr, mDerefPie(hndl)->arcEnd.v);
  290.             ccat   (cptr, ",");
  291.             ccatdec(cptr, mDerefPie(hndl)->arcEnd.h);
  292.             ccat   (cptr, ")");
  293.             ccatchr(cptr, 13, 1);
  294.             return(true);
  295.             break;
  296. #endif
  297.  
  298.         case CLICKMESSAGE:
  299.             TRectObj(hndl, message, data);
  300.             click = (ClickInfo *)data;
  301.             if (click->message == CLICKDRAG) {
  302.                 AddPt(click->offset, &mDerefPie(hndl)->center);
  303.                 AddPt(click->offset, &mDerefPie(hndl)->arcBegin);
  304.                 AddPt(click->offset, &mDerefPie(hndl)->arcEnd);
  305.             }
  306.             break;
  307.  
  308.         case SIZEMESSAGE:
  309.             click = (ClickInfo *)data;
  310.             if (click->grabber <= 4) {
  311.                 newSize = TRectObj(hndl, message, data);
  312.                 click = (ClickInfo *)data;
  313.                 if (flip = (click->oldFlip ^ click->newFlip)) {
  314.                     arcs = mDerefPie(hndl)->arcStart;
  315.                     arcl = mDerefPie(hndl)->arcLength;
  316.                     if (flip & VFLIPOBJ) {
  317.                         arcs -= (i = (arcs < 180) ? 0 : 180);
  318.                         arcs = 180 - arcs;
  319.                         arcl = -arcl;
  320.                         arcs += i;
  321.                     }
  322.                     if (flip & HFLIPOBJ) {
  323.                         arcs = 360 - arcs;
  324.                         arcl = -arcl;
  325.                     }
  326.                     mDerefPie(hndl)->arcStart  = arcs;
  327.                     mDerefPie(hndl)->arcLength = arcl;
  328.                 }
  329.                 CalcPiePoints(hndl);
  330.                 return(newSize);
  331.             }
  332.  
  333.             GetMouse(&curMouse);
  334.             curMouse.h += click->offset.h;
  335.             curMouse.v += click->offset.v;
  336.             rct = mDerefPie(hndl)->arc;
  337.  
  338.             arcs = arcs2 = mDerefPie(hndl)->arcStart;
  339.             arcl = arcl2 = mDerefPie(hndl)->arcLength;
  340.  
  341.             PtToAngle(&rct, curMouse, &angle);
  342.  
  343.             if (click->grabber == 6) {        /* Handle 2nd grabber as reverse first grabber case. */
  344.                 click->grabber = 5;
  345.                 arcs += arcl;
  346.                 arcl  = -arcl;
  347.                 while (arcs >  360) arcs -= 360;
  348.                 while (arcs <    0) arcs += 360;
  349.             }
  350.  
  351.             diff = angle - arcs;
  352.             arcs = angle;
  353.             OSEventAvail(nullEvent, &option);
  354.             if (!(option.modifiers & shiftKey)) {
  355.                 while (diff >  180) diff -= 360;        /* Force 1 change to be less than 180. */
  356.                 while (diff < -180) diff += 360;
  357.                 arcl   -= diff;
  358.                 while (arcl >  360) arcl -= 360;
  359.                 while (arcl < -360) arcl += 360;
  360.             }
  361.  
  362.             if ((arcs != arcs2) || (arcl != arcl2)) {
  363.                 mDerefPie(hndl)->arcStart  = arcs;
  364.                 mDerefPie(hndl)->arcLength = arcl;
  365.                 CalcPiePoints(hndl);
  366.                 return(true);
  367.             }
  368.             break;
  369.  
  370.         default:
  371.             break;
  372.     }
  373.  
  374.     return(noErr);
  375. }
  376.  
  377.  
  378.  
  379. /*****************************************************************************/
  380.  
  381.  
  382.  
  383. #pragma segment DrawObjects
  384. OSErr    CalcPiePoints(TreeObjHndl hndl)
  385. {
  386.     OSErr        err;
  387.     Rect        rct;
  388.     short        arcs, arcl, i, angle;
  389.     RgnHandle    rgn;
  390.     Point        pt;
  391.     long        ll;
  392.     LayerObj    pieLayer;
  393.  
  394.     if (err = NewLayer(&pieLayer, nil, PieLayerProc, nil, 0, (long)hndl)) return(err);
  395.  
  396.     rct  = mDerefPie(hndl)->arc;
  397.     arcs = mDerefPie(hndl)->arcStart;
  398.     arcl = mDerefPie(hndl)->arcLength;
  399.  
  400.     SetLayerWorld(pieLayer);
  401.     rgn = NewRgn();
  402.  
  403.     EraseRect(&rct);
  404.     FillArc(&rct, 90, 90, (ConstPatternParam)&qd.black);
  405.  
  406.     BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  407.     pt = *(Point *)(&(*rgn)->rgnBBox);
  408.     ll = PinRect(&rct, pt);
  409.     pt = *(Point *)≪
  410.     mDerefPie(hndl)->center = pt;
  411.  
  412.     for (i = 0; i < 2; ++i) {
  413.         angle = (i) ? (arcs + arcl) : (arcs);
  414.         while (angle < 0)    angle += 360;
  415.         while (angle >= 360) angle -= 360;
  416.         EraseRect(&rct);
  417.         if (angle < 90) {
  418.             FillArc(&rct, angle, 90, (ConstPatternParam)&qd.black);
  419.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  420.             pt.v = (*rgn)->rgnBBox.top;
  421.             EraseRect(&rct);
  422.             FillArc(&rct, angle, -90, (ConstPatternParam)&qd.black);
  423.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  424.             pt.h = (*rgn)->rgnBBox.right;
  425.             if (angle > 45)
  426.                 --pt.h;
  427.         }
  428.         if ((angle >= 90) && (angle < 180)) {
  429.             FillArc(&rct, angle, 90, (ConstPatternParam)&qd.black);
  430.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  431.             pt.h = (*rgn)->rgnBBox.right;
  432.             EraseRect(&rct);
  433.             FillArc(&rct, angle, -90, (ConstPatternParam)&qd.black);
  434.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  435.             pt.v = (*rgn)->rgnBBox.bottom;
  436.             if (angle < 135)
  437.                 --pt.h;
  438.             else
  439.                 --pt.v;
  440.         }
  441.         if ((angle >= 180) && (angle < 270)) {
  442.             FillArc(&rct, angle, 90, (ConstPatternParam)&qd.black);
  443.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  444.             pt.v = (*rgn)->rgnBBox.bottom;
  445.             EraseRect(&rct);
  446.             FillArc(&rct, angle, -90, (ConstPatternParam)&qd.black);
  447.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  448.             pt.h = (*rgn)->rgnBBox.left;
  449.             if (angle < 225)
  450.                 --pt.v;
  451.         }
  452.         if (angle >= 270) {
  453.             FillArc(&rct, angle, 90, (ConstPatternParam)&qd.black);
  454.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  455.             pt.h = (*rgn)->rgnBBox.left;
  456.             EraseRect(&rct);
  457.             FillArc(&rct, angle, -90, (ConstPatternParam)&qd.black);
  458.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  459.             pt.v = (*rgn)->rgnBBox.top;
  460.         }
  461.         ll = PinRect(&rct, pt);
  462.         pt = *(Point *)≪
  463.         (i) ? (mDerefPie(hndl)->arcEnd = pt) : (mDerefPie(hndl)->arcBegin = pt);
  464.     }
  465.  
  466.     DisposeRgn(rgn);
  467.     ResetLayerWorld(pieLayer);
  468.     DisposeLayer(pieLayer);
  469.     return(noErr);
  470. }
  471.  
  472.  
  473.  
  474. /*****************************************************************************/
  475.  
  476.  
  477.  
  478. static OSErr    PieLayerProc(LayerObj theLayer, short message)
  479. {
  480.     OSErr        err;
  481.     TreeObjHndl    pie;
  482.     Rect        rct;
  483.     CGrafPtr    keepPort;
  484.     GDHandle    keepGDevice;
  485.     GWorldPtr    layerWorld;
  486.  
  487.     switch (message) {
  488.         case kLayerInit:
  489.             err = noErr;
  490.             if (theLayer) {
  491.                 if (!(*theLayer)->layerPort) {
  492.                     pie = (TreeObjHndl)(*theLayer)->layerData;
  493.                     rct = mDerefPie(pie)->arc;
  494.                     GetGWorld(&keepPort, &keepGDevice);        /* Keep the GWorld. */
  495.                     err = NewGWorld(&layerWorld, 1, &rct, nil, nil, 0);
  496.                     if (err == noErr) {
  497.                         (*theLayer)->layerOwnsPort = true;
  498.                         SetPort((*theLayer)->layerPort = (GrafPtr)layerWorld);
  499.                         SetOrigin(rct.left, rct.top);
  500.                         EraseRect(&rct);
  501.                     }
  502.                     SetGWorld(keepPort, keepGDevice);        /* Restore the kept GWorld. */
  503.                 }
  504.             }
  505.             else err = paramErr;
  506.             break;
  507.  
  508.         default:
  509.             err = DefaultLayerProc(theLayer, message);
  510.                 /* Default behavior for everything else. */
  511.             break;
  512.     }
  513.  
  514.     return(err);
  515. }
  516.  
  517.  
  518.  
  519.